package com.mui.manager
{
	import flash.accessibility.*;
	import flash.display.*;
	import flash.events.*;
	import flash.geom.*;
	import flash.utils.*;
	
	public class ToolTipsManager extends Sprite
	{
		private var area:DisplayObject;
		private var toolTipContent:IToolTip;
		private var toolTipLayer:DisplayObjectContainer;
		private var delayTimer:Timer;
		private var _this:ToolTipsManager;
		private static var toolClassMap:Object = {};
		private static var classId:int = 0;
		private static var _instance:ToolTipsManager = null;
		private static var _defaultRenderClass:Class;
		
		public function ToolTipsManager(point:DisplayObjectContainer)
		{
			visible = false;
			var obj:Boolean = false;
			mouseChildren = false;
			mouseEnabled = obj;
			this.toolTipLayer = point;
			this._this = this;
			point.addChild(this);
		}
		
		public function show(point:DisplayObject) : void
		{
			var obj:Object = null;
			var toolTipData:Object = null;
			var contain:DisplayObjectContainer = null;
			this.area.addEventListener(MouseEvent.MOUSE_MOVE, this.handler);
			if (point.accessibilityProperties)
			{
				this.clearConetnt();
				obj = toolClassMap[point.accessibilityProperties.description];
				if (obj.areaItem is IToolTipItem)
				{
					toolTipData = (obj.areaItem as IToolTipItem).toolTipData;
				}
				else
				{
					toolTipData = obj.toolTipData;
				}
				if (toolTipData != null)
				{
					this.toolTipContent = ToolTipPool.getObject(obj.toolTipClass as Class);
					(this.toolTipContent as DisplayObject).visible = true;
					this.toolTipContent.data = toolTipData;
					contain = this.toolTipContent as DisplayObjectContainer;
					contain.mouseChildren = false;
					contain.mouseEnabled = false;
					addChild(contain);
				}
			}
		}
		
		public function hide() : void
		{
			this.clearDelayCount();
			this.clearConetnt();
			if (this.area)
			{
				this.area.removeEventListener(MouseEvent.MOUSE_DOWN, this.handler);
				this.area.removeEventListener(MouseEvent.MOUSE_OUT, this.handler);
				this.area.removeEventListener(MouseEvent.MOUSE_MOVE, this.handler);
				this.area = null;
			}
			visible = false;
		}
		
		private function clearConetnt() : void
		{
			var displayobj:DisplayObject = null;
			if (this.toolTipContent)
			{
				ToolTipPool.disposeObject(this.toolTipContent);
				displayobj = this.toolTipContent as DisplayObject;
				displayobj.visible = false;
				if (displayobj.hasOwnProperty("dispose"))
				{
					var obj:* = displayobj;
					obj.displayobj["dispose"]();
				}
				if (this.contains(displayobj))
				{
					this.removeChild(displayobj);
				}
				this.toolTipContent = null;
			}
		}
		
		public function move(point:Point) : void
		{
			var obj:* = this.parent.globalToLocal(point);
			this.x = obj.x + 15;
			if (this.x > this.toolTipLayer.stage.stageWidth - this.width - 6)
			{
				this.x = obj.x - this.width - 6;
			}
			
			this.y = obj.y + 6;
			if (this.y + this.height > this.toolTipLayer.stage.stageHeight)
			{
				this.y = this.toolTipLayer.stage.stageHeight - this.height;
			}
			if (!visible)
			{
				visible = true;
			}
		}
		
		private function handler(event:MouseEvent) : void
		{
			var obj:DisplayObject = null;
			switch(event.type)
			{
				case MouseEvent.MOUSE_OUT:
				{
					this.hide();
					break;
				}
				case MouseEvent.MOUSE_DOWN:
				{
					this.hide();
					break;
				}
				case MouseEvent.MOUSE_UP:
				{
					this.hide();
					break;
				}
				case MouseEvent.MOUSE_MOVE:
				{
					this.move(new Point(event.stageX, event.stageY));
					break;
				}
				case MouseEvent.MOUSE_OVER:
				{
					this.hide();
					obj = event.currentTarget as DisplayObject;
					if (obj.alpha == 1)
					{
						this.area = event.currentTarget as DisplayObject;
						this.startDelayCount();
					}
					break;
				}
				default:
				{
					break;
				}
			}
		}
		
		private function startDelayCount() : void
		{
			if (!this.delayTimer)
			{
				this.delayTimer = new Timer(500, 1);
				this.delayTimer.addEventListener(TimerEvent.TIMER_COMPLETE, this.showAfterDelay);
			}
			this.delayTimer.reset();
			this.delayTimer.start();
			this.area.addEventListener(MouseEvent.MOUSE_DOWN, this.handler);
			this.area.addEventListener(MouseEvent.MOUSE_OUT, this.handler);
			this.area.addEventListener(MouseEvent.MOUSE_UP, this.handler);
		}
		
		private function clearDelayCount() : void
		{
			if (this.delayTimer)
			{
				this.delayTimer.stop();
			}
		}
		
		private function showAfterDelay(event:TimerEvent) : void
		{
			this.show(this.area);
			var obj:* = new Point(this.area.mouseX, this.area.mouseY);
			obj = this.area.localToGlobal(obj);
			this.move(obj);
		}
		
		public static function get defaultRenderClass() : Class
		{
			return _defaultRenderClass;
		}
		
		public static function set defaultRenderClass(defaultRenderClass:Class) : void
		{
			_defaultRenderClass = defaultRenderClass;
		}
		
		public static function init(contain:DisplayObjectContainer) : void
		{
			if (_instance == null)
			{
				_instance = new ToolTipsManager(contain);
			}
		}
		
		public static function register(area:*, renderClass:Class = null, toolTipData:Object = null) : void
		{
			var prop:AccessibilityProperties;
			var vTargetArea:EventDispatcher;
			
			var handler:Function =
				function (event:MouseEvent) : void
				{
					var obj:DisplayObject = null;
					switch(event.type)
					{
						case MouseEvent.MOUSE_OUT:
						{
							_instance.hide();
							break;
						}
						case MouseEvent.MOUSE_DOWN:
						{
							_instance.hide();
							break;
						}
						case MouseEvent.MOUSE_UP:
						{
							_instance.hide();
							break;
						}
						case MouseEvent.MOUSE_MOVE:
						{
							_instance.move(new Point(event.stageX, event.stageY));
							break;
						}
						case MouseEvent.MOUSE_OVER:
						{
							_instance.hide();
							obj = event.currentTarget as DisplayObject;
							if (obj["accessibilityProperties"] == null)
							{
								obj["accessibilityProperties"] = prop;
							}
							if (obj.alpha == 1)
							{
								_instance.area = event.currentTarget as DisplayObject;
								if (!_instance.delayTimer)
								{
									_instance.delayTimer = new Timer(200, 1);
									_instance.delayTimer.addEventListener(TimerEvent.TIMER_COMPLETE, _instance.showAfterDelay);
								}
								_instance.delayTimer.reset();
								_instance.delayTimer.start();
								_instance.area.addEventListener(MouseEvent.MOUSE_DOWN, _instance.handler);
								vTargetArea.addEventListener(MouseEvent.MOUSE_OUT, _instance.handler);
								_instance.area.addEventListener(MouseEvent.MOUSE_UP, _instance.handler);
							}
							break;
						}
						default:
						{
							break;
						}
					}
					
				};
			
			if (_instance == null)
			{
				throw new Error("ToolTipsManager 未初始化");
			}
			
			prop = new AccessibilityProperties();
			classId = classId + 1;
			var vId:* = "Item" + classId;
			if (_defaultRenderClass == null && renderClass == null)
			{
				throw new Error("ToolTipManger的dfaultRenderClass未定义");
			}
			if (renderClass != null)
			{
				toolClassMap[vId] = {toolTipClass:renderClass, areaItem:area, toolTipData:toolTipData};
			}
			else
			{
				toolClassMap[vId] = {toolTipClass:_defaultRenderClass, areaItem:area, toolTipData:toolTipData};
			}
			prop.description = vId;
			vTargetArea = area as EventDispatcher;
			vTargetArea.addEventListener(MouseEvent.MOUSE_OVER, handler);
		}
		
		public static function unregister(event:EventDispatcher) : void
		{
			if (_instance != null && event)
			{
				event.removeEventListener(MouseEvent.MOUSE_OVER, _instance.handler);
			}
		}
	}
}
